/*
 *  Vector4.h
 *  zray-gui
 *
 *  Created by czalkin on 2/1/09.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */

#ifndef VECTOR4_H_
#define VECTOR4_H_

#include <math.h>
#include "Vector3.hpp"

class Matrix4;

class Vector4
{
	friend class Matrix4;
	friend class Vector3;
	
public:
	Vector4() { v[0] = 0.0f; v[1] = 0.0f; v[2] = 0.0f; v[3] = 0.0f; }
	Vector4( const Vector3 &c, float w ) { v[0] = c.v[0]; v[1] = c.v[1]; v[2] = c.v[2]; v[3] = w; }
	Vector4( float x, float y, float z, float w )
	{
		v[0] = x; v[1] = y; v[2] = z; v[3] = w;
	}
	
	Vector4( float* in ) { v[0] = in[0]; v[1] = in[1]; v[2] = in[2]; v[3] = in[3]; }
		
	float operator[]( const int index ) const { return v[index]; }
		
	inline void set( const int index, float val ) { v[index] = val; }
	inline float get( const int index ) const { return v[index]; }
		
	
//		inline Vector3 cross( const Vector3 &rhs ) const
//		{
//			return Vector3( v[1]*rhs.v[2]-v[2]*rhs.v[1],  v[2]*rhs.v[0] - v[0]*rhs.v[2],  v[0]*rhs.v[1] - v[1]*rhs.v[0] );
//		}
		
		inline Vector4& operator+=( const Vector4 &rhs )
		{
			v[0] += rhs.v[0];
			v[1] += rhs.v[1];
			v[2] += rhs.v[2];
			v[3] += rhs.v[3];
			return *this;
		}
		
		inline Vector4 operator*=( const float s )
		{
			v[0] *= s;
			v[1] *= s;
			v[2] *= s;
			v[3] *= s;
			return *this;
		}
		
		inline Vector4 operator+( const Vector4 &rhs ) const
		{
			return Vector4( v[0] + rhs.v[0], v[1] + rhs.v[1], v[2] + rhs.v[2], v[3] + rhs.v[3] );
		}
		
		inline Vector4 operator*( const float s ) const
		{
			return Vector4( v[0]*s, v[1]*s, v[2]*s, v[3]*s );
		}
		
		inline Vector4 operator-( const Vector4 &rhs ) const
		{
			return Vector4( v[0] - rhs.v[0], v[1] - rhs.v[1], v[2] - rhs.v[2], v[3] - rhs.v[3] );
		}
		
		inline float dot( const Vector4 &rhs ) const
		{
			return v[0]*rhs.v[0] + v[1]*rhs.v[1] + v[2]*rhs.v[2] + v[3]*rhs.v[3];
		}
		
		inline float lengthSq() const
		{
			return v[0]*v[0] + v[1]*v[1] + v[2]*v[2] + v[3]*v[3];
		}
		
		inline float length() const
		{
			return sqrt( lengthSq() );
		}
		
		inline float normalize_inPlace()
		{
			const float len = length();
			v[0] /= len;
			v[1] /= len;
			v[2] /= len;
			v[3] /= len;
			return len;
		}
		
		Vector3 homogeneous() const
		{
			return Vector3( v[0]/v[3], v[1]/v[3], v[2]/v[3] );
		}
	
		inline Vector4 normalize() const
		{
			const float len = length();
			return Vector4( v[0] / len, v[1] / len, v[2] /len, v[3] / len );
		}
	
	
		Vector4 operator*( const Matrix4 &mat ) const;
protected:
	float v[4];
};

#endif
